using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using FarseerGames.FarseerPhysics;
using NetPong.PongClasses3d;
using XNALibrary;
using XNALibrary.OmniCamera;
using XNALibrary.ZCAMERA;
using NetPong;
using XNALibrary.Effects;

namespace TestGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class TestGame : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;

        Level3d level;
        Ball3d ball;
        Ball3d bigBall;
        LightBulb bulb1, bulb2, bulb3;

        InputHandler input;
        RenderControl renderControl;
        PhysicsSimulator physicsSimulator;

        public TestGame()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            #region Rendering Initialization
            //CAMERA PARAMETERS
            Vector3 camPosition = new Vector3(0, 500, 0);
            Vector3 camDirection = Vector3.Down;
            Vector3 camUp = Vector3.Left;
            Vector3 camTargetPos = Vector3.Zero;
            ICamera camera = new FPCamera(this.GraphicsDevice, camPosition, camDirection, camUp, camTargetPos);
            renderControl = new RenderControl(this, camera);
            #endregion

            physicsSimulator = new PhysicsSimulator();
            physicsSimulator.Enabled = true;
            
            input = new InputHandler(this);

            ball = new Ball3d(new Vector2(20,20), null,20, physicsSimulator, renderControl.ContentManager);
            renderControl.Renderables.Add(ball);
            bigBall = new Ball3d(Vector2.Zero, null, 20, physicsSimulator, renderControl.ContentManager, input);
            renderControl.Renderables.Add(bigBall);
            bigBall.body.ApplyImpulse(new Vector2(20,-15));
            
            level = new Level3d(renderControl.ContentManager.Load<Model>(".\\Content\\Models\\Board"), physicsSimulator);
            renderControl.Renderables.Add(level);

            //set CAMERA to ZCamera
            renderControl.CurrentCamera = new ZCamera(input, bigBall);

            //CODE ADDED BY BEN BATMAN
            //*********************************************************************

            ball.rigidBody.effect = new BenCustomEffect(Content.Load<Effect>("Shaders/LightWave"));

            ball.rigidBody.effect.ModelTexture = Content.Load<Texture2D>("Textures/metal2");

            ((BenCustomEffect)(ball.rigidBody.effect)).LightsEnabled = false;

            ball.rigidBody.effect.SetupParameters();

            level.rigidBody.effect = new ZCustomEffect(Content.Load<Effect>("Shaders/LightWave"));
            level.rigidBody.effect.ModelTexture = Content.Load<Texture2D>("Textures/sand");
            
            //*********************************************************************
            
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            //CODE ADDED BY BEN BATMAN
            //*********************************************************************

            PointLight[] colLights = new PointLight[4];

            PointLight Light = new PointLight(new Vector3(112, 3, -113), 1.0f, Color.Green);
            colLights[0] = Light;

            Light = new PointLight(new Vector3(-116, 3, -113), 1.0f, Color.Red);
            colLights[1] = Light;

            Light = new PointLight(new Vector3(-116, 3, 131), 1.0f, Color.Blue);
            colLights[2] = Light;

            Light = new PointLight(new Vector3(116, 3, 131), 1.0f, Color.Orange);
            colLights[3] = Light;

           // ((BenCustomEffect)(ball.rigidBody.effect)).AddLights(colLights);

            //*********************************************************************

            Model lightbulb = renderControl.ContentManager.Load<Model>(".\\Content\\Models\\lightbulb");
            bulb1 = new LightBulb(lightbulb, new Vector3(100, 100, 0), new Vector3(0, 180, 0));
            bulb1.effect = new LightBulbEffect(renderControl.ContentManager.Load<Effect>(".\\Content\\Shaders\\LightBulb"));
            bulb1.Color = Color.Blue;
            renderControl.Renderables.Add(bulb1);
            renderControl.LightSources.Add(bulb1);

            bulb2 = new LightBulb(lightbulb, new Vector3(-100, 100, 0), new Vector3(0, 180, 0));
            bulb2.effect = new LightBulbEffect(renderControl.ContentManager.Load<Effect>(".\\Content\\Shaders\\LightBulb"));
            bulb2.Color = Color.Red;
            renderControl.Renderables.Add(bulb2);
            renderControl.LightSources.Add(bulb2);

            bulb3 = new LightBulb(lightbulb, new Vector3(0,100,100), new Vector3(0, 180, 0));
            bulb3.effect = new LightBulbEffect(renderControl.ContentManager.Load<Effect>(".\\Content\\Shaders\\LightBulb"));
            bulb3.Color = Color.Yellow;
            renderControl.Renderables.Add(bulb3);
            renderControl.LightSources.Add(bulb3);

            //renderControl.LightSources.Add(new PointLight(new Vector3(100,0,0),3.0f,Color.Blue));

            //Jon's Effect
            CustomEffect jEffect = new JonCustomEffect(
                      renderControl.ContentManager.Load<Effect>(".\\Content\\Shaders\\GlossMap"),
                      renderControl.ContentManager.Load<Texture2D>(".\\Content\\Textures\\colormap"),
                      renderControl.ContentManager.Load<Texture2D>(".\\Content\\Textures\\glossmap"));

            CustomEffect zEffect = new ZCustomEffect(renderControl.ContentManager.Load<Effect>(".\\Content\\Shaders\\LightWave"));
            bigBall.rigidBody.effect = jEffect;
            ball.rigidBody.effect = zEffect;

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            input.Update();


            physicsSimulator.Update(gameTime.ElapsedGameTime.Milliseconds * .001f);


            bigBall.Update();

            if (input.WasPressed(0, Buttons.A, Keys.B))
                ((BenCustomEffect)(ball.rigidBody.effect)).StartWave(30.0f);

            if(input.WasPressed(0,Buttons.B,Keys.D1))
            {
                bulb1.IsOn = !bulb1.IsOn;
            }
            if (input.WasPressed(0, Buttons.B, Keys.D2))
            {
                bulb2.IsOn = !bulb2.IsOn;
            }
            if (input.WasPressed(0, Buttons.B, Keys.D3))
            {
                bulb3.IsOn = !bulb3.IsOn;
            }

            //I made this call primarily for updating cameras via user input
            renderControl.Update(gameTime);
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            renderControl.Draw(gameTime);

            base.Draw(gameTime);
        }
    }
}
